package com.android.functionmanagement.request.http;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.net.URI;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.List;

import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.ProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.params.ConnPerRoute;
import org.apache.http.conn.params.ConnPerRouteBean;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.DefaultRedirectHandler;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HttpContext;
import org.json.JSONObject;

import com.android.functionmanagement.globle.ConstantGloble;
import com.android.functionmanagement.globle.LogGloble;
import com.android.functionmanagement.util.DeviceUtils;
import com.android.functionmanagement.util.StringUtil;

import android.accounts.NetworkErrorException;
import android.content.Context;

/**
 * 描述:BaseHttpEngine
 * <p />
 * 
 * 基于http的基础Engine
 * <p />
 * 
 * 
 */
public abstract class BaseHttpEngine {
	/** 发送请求的对象 */
	protected static DefaultHttpClient sClient; // 发送请求的对象
	/** 是否需要设置代理 */
	protected static boolean needProxy = false; // 是否需要设置代理
	/** 设置代理的主机名 */
	protected static String hostname = ""; // 设置代理的主机名
	/** 设置代理的端口 */
	protected static int hostport = 0; // 设置代理的端口

	protected boolean cancleFlag = false;
	protected HttpGet httpGet = null;
	protected HttpPost httppost = null;

	protected boolean alertFlag = true; // 是否弹出通讯进度条

	private static final String TAG = "BaseHttpEngine"; 

	public void setCancleFlag(boolean cancleFlag) {
		this.cancleFlag = cancleFlag;
		if (this.cancleFlag) {
			if (httpGet != null) {
				httpGet.abort();
			}
			if (httppost != null) {
				httppost.abort();
			}
		}
	}

	/**
	 * 方法功能说明：发送http请求，根据传回来的参数method的不同，判断调用httpGet或者httpPost方法
	 */
	public abstract HashMap<String, Object> httpSend(String url, String method,
			Context context, JSONObject json,HashMap<String, Object> headerArg,File file)
			throws Exception;

	/**
	 * 方法功能说明：初始化代理，在这个方法中设置需要的代理配置，它主要是根据当前默认的接入点来设置这个代理
	 * 
	 * @param con
	 * @throws NoSuchAlgorithmException
	 * @throws KeyManagementException
	 * @throws KeyStoreException
	 * @throws IOException
	 * @throws UnrecoverableKeyException
	 */
	public void initProxy(Context con) throws Exception {
		LogGloble.v(TAG, "initProxy ...");
		// 设置基础数据
		HttpParams params = new BasicHttpParams();// 设置参数列表对象
		HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);// 设置版本
		HttpProtocolParams.setContentCharset(params,
				ConstantGloble.CONTENT_CHARSET);// 设置编码类型
		HttpProtocolParams.setUseExpectContinue(params, true);// 设置异常是否继续???
		HttpProtocolParams.setUserAgent(params, getUserAgent());

		// 设置链接池
		ConnPerRoute connPerRoute = new ConnPerRouteBean(
				ConstantGloble.CONN_PER_ROUTE_BEAN);
		ConnManagerParams.setMaxConnectionsPerRoute(params, connPerRoute);// 设置每个路由最大链接数
		ConnManagerParams.setMaxTotalConnections(params,
				ConstantGloble.MAX_TOTAL_CONNECTIONS);// 设置最大链接数

		// 设置超时
		HttpConnectionParams.setStaleCheckingEnabled(params, false);
		HttpConnectionParams.setConnectionTimeout(params,
				ConstantGloble.CONNECTION_TIME_OUT);// 设置链接超时时间
		HttpConnectionParams.setSoTimeout(params,
				ConstantGloble.SOCKET_TIME_OUT);// 设置socket超时时间
		HttpConnectionParams.setSocketBufferSize(params,
				ConstantGloble.SOCKET_BUFFER_SIZE);// 设置sokect缓存最大字节数

		// 设置不验证证书
		KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
		trustStore.load(null, null);

		// 设置http/https通讯模式
		SchemeRegistry schReg = new SchemeRegistry(); // 注册通讯模式对象

		schReg.register(new Scheme(ConstantGloble.HTTP, PlainSocketFactory
				.getSocketFactory(), ConstantGloble.HTTP_PORT));// 注册http模式，普通socket

		// 生成链接管理对象，把设置的参数和模式设置进去
		ClientConnectionManager conMgr = new ThreadSafeClientConnManager(
				params, schReg);
		sClient = new DefaultHttpClient(conMgr, params);// 发送请求的对象

		setRedirection(); // 设置重定向

		// 获取默认通讯代理主机ip
		String proxyHost = android.net.Proxy.getDefaultHost();

		// 根据代理地址是否为空设置是否需要代理
		needProxy = (proxyHost != null);

		// // 判断如果wifi开启，就不需要设置代理了
		// if (FidgetManager.getWifiManager().isWifiEnabled()) {
		// needProxy = false;
		// }
		if (needProxy) {// 如果需要代理
			hostname = android.net.Proxy.getDefaultHost();// 代理主机名
			hostport = android.net.Proxy.getDefaultPort();// 代理主机端口
			HttpHost proxy = new HttpHost(hostname, hostport);// 代理主机对象
			sClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,
					proxy);// 请求对象设置代理
		} else {
			hostname = "";
			hostport = 0;
		}
	}

	/**
	 * 设置重定向
	 */
	protected void setRedirection() {
		sClient.setRedirectHandler(new DefaultRedirectHandler() {
			@Override
			public boolean isRedirectRequested(HttpResponse response,
					HttpContext context) {
				boolean isRedirect = super.isRedirectRequested(response,
						context);
				if (!isRedirect) {
					int responseCode = response.getStatusLine().getStatusCode();
					if (responseCode == HttpStatus.SC_MOVED_TEMPORARILY
							|| responseCode == HttpStatus.SC_MOVED_PERMANENTLY
							|| responseCode == HttpStatus.SC_SEE_OTHER
							|| responseCode == HttpStatus.SC_TEMPORARY_REDIRECT) {
						return true;
					}
				}
				return isRedirect;
			}

			@Override
			public URI getLocationURI(HttpResponse response, HttpContext context)
					throws ProtocolException {
				String newUri = response.getLastHeader("Location").getValue();
				return URI.create(newUri);
			}

		});
	}

	/**
	 * 方法功能说明：发送get请求
	 * 
	 * @param get
	 *            HttpGet类的实例对象
	 * @return HttpResponse 对返回的流，响应头等信息的封装
	 * @throws NoSuchAlgorithmException
	 * @throws KeyManagementException
	 * @throws UnrecoverableKeyException
	 * @throws CertificateException
	 * @throws KeyStoreException
	 * @see BTCHttpConnection#httpSend（）
	 */
	public HttpResponse execute(HttpGet get, Context con) throws Exception {
		if (!DeviceUtils.haveInternet(con)) {
			throw new NetworkErrorException("错误信息");
		}
		initProxy(con);
		LogGloble.v(TAG, "execute HttpGet " + get.hashCode() + " start ...");
		HttpResponse response;
		if (needProxy) {
			response = sClient.execute(new HttpHost(hostname, hostport), get);
		} else {
			response = sClient.execute(get);
		}
		LogGloble.v(TAG, "execute HttpGet " + get.hashCode() + " finish ...");
		sClient = null;
		return response;
	}

	/**
	 * 方法功能说明：发送Post请求
	 * 
	 * @param get
	 *            HttpPost类的实例对象
	 * @return HttpResponse 对返回的流，响应头等信息的封装
	 * @throws NoSuchAlgorithmException
	 * @throws KeyManagementException
	 * @throws UnrecoverableKeyException
	 * @throws CertificateException
	 * @throws KeyStoreException
	 * @see BTCHttpConnection#httpSend()
	 */
	public HttpResponse execute(HttpPost post, Context con) throws Exception {
		if (!DeviceUtils.haveInternet(con)) {
			throw new NetworkErrorException("错误信息");
		}
		initProxy(con);
		LogGloble.v(TAG, "execute HttpPost " + post.hashCode() + " start ...");
		HttpResponse response = null;
		if (needProxy) {
			response = sClient.execute(new HttpHost(hostname, hostport), post);
		} else {
			response = sClient.execute(post);
			LogGloble.v(TAG, "execute HttpPost StatusCode: "
					+ response.getStatusLine().getStatusCode());
			LogGloble.v(TAG, "execute HttpPost " + post.hashCode()
					+ " finish ...");

		}

		sClient = null;
		return response;
	}

	/**
	 * 获取cookie保存内容
	 * 
	 * @return
	 */
	public static synchronized CookieStore getCookieStore() {
		return sClient.getCookieStore();
	}

	/**
	 * 方法功能说明：把流转换成字符串
	 * 
	 * @param
	 * @return String
	 * @see
	 */
	public static String inputStream2String(InputStream inStream)
			throws Exception {
		ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
		try {
			byte[] buffer = new byte[1024];
			int len = -1;
			while ((len = inStream.read(buffer)) != -1) {// 把字符串读取到buffer，并判断是否读取到结尾
				outSteam.write(buffer, 0, len);// 把buffer写入到输出流
			}

			// 把输出流根据UTF-8编码转为字符串对象返回
			return new String(outSteam.toByteArray(),
					ConstantGloble.DEFAULT_ENCODE);
		} finally {
			outSteam.close();// 读取完毕关闭输出流
		}

	}

	/**
	 * 取得user agent
	 * 
	 * @return
	 */
	public static String getUserAgent() {
		return ConstantGloble.APP_USER_AGENT_PREFIX;
	}

	/**
	 * 为http请求URL添加参数
	 * 
	 * @param url
	 *            http请求url
	 * @param nameValuePairs
	 *            参数键值对
	 * @return url (带参数)
	 * 
	 */
	protected String addParamsToHttpUrl(String url,
			JSONObject json) {
		if (StringUtil.isNullOrEmpty(json)) {
			return url;
		}

		// 判断URL是否以问号结尾
		if (!url.endsWith("?")) {
			url += "?";
		}

		// 生成参数字符串
		String paramString = null;//URLEncodedUtils.format(nameValuePairs, "utf-8");  //暂时不用get处理
		url += paramString;

		LogGloble.i(TAG, "addParamsToHttpUrl coded url->" + url);

		return url;
	}

	
}
